package com.lvy.hczn.front.business.service.impl;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.lvy.hczn.front.business.mapper.WarehousingOutMapper;
import com.lvy.hczn.front.system.service.SpuService;
import com.lvy.hczn.front.business.service.WarehousingOutService;
import com.lvy.hczn.front.common.constant.MqConstants;
import com.lvy.hczn.front.common.exception.UtilException;
import com.lvy.hczn.front.system.domain.business.Spu;
import com.lvy.hczn.front.system.domain.business.Warehouse;
import com.lvy.hczn.front.system.domain.business.WarehousingOut;
import com.lvy.hczn.front.system.domain.business.dto.WarehousingEntryBoxDto;
import com.lvy.hczn.front.system.domain.business.dto.WarehousingOutDto;
import com.lvy.hczn.front.system.service.WarehouseService;
import com.lvy.hczn.mq.rocket.ParamInfo;
import com.lvy.hczn.mq.rocket.ProducerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lvy.hczn.front.common.core.text.Convert;

/**
 * 商品出库单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-05-30
 */
@Service
@Slf4j
public class WarehousingOutServiceImpl extends ServiceImpl<WarehousingOutMapper, WarehousingOut> implements WarehousingOutService {
    @Autowired
    private WarehousingOutMapper warehousingOutMapper;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private ProducerUtil producerUtil;

    @Autowired
    private SpuService spuService;

    /**
     * 查询商品出库单
     *
     * @param id 商品出库单主键
     * @return 商品出库单
     */
    @Override
    public WarehousingOut selectWarehousingOutById(String id) {
        return warehousingOutMapper.selectById(id);
    }

    /**
     * 查询商品出库单列表
     *
     * @param warehousingOut 商品出库单
     * @return 商品出库单
     */
    @Override
    public List<WarehousingOut> selectWarehousingOutList(WarehousingOut warehousingOut) {
        return warehousingOutMapper.selectWarehousingOutList(warehousingOut);
    }

    /**
     * 新增商品出库单
     *
     * @param warehousingOut 商品出库单
     * @return 结果
     */
    @Override
    public int insertWarehousingOut(WarehousingOut warehousingOut) {
        return warehousingOutMapper.insert(warehousingOut);
    }

    /**
     * 修改商品出库单
     *
     * @param warehousingOut 商品出库单
     * @return 结果
     */
    @Override
    public int updateWarehousingOut(WarehousingOut warehousingOut) {
        return warehousingOutMapper.updateById(warehousingOut);
    }

    /**
     * 批量删除商品出库单
     *
     * @param ids 需要删除的商品出库单主键
     * @return 结果
     */
    @Override
    public int deleteWarehousingOutByIds(String ids) {
        if (StrUtil.isEmpty(ids)) {
            throw new UtilException("ID为空");
        }
        String[] arrId = Convert.toStrArray(ids);
        for (String id : arrId) {
            super.removeById(id);
        }
        return arrId.length;
    }

    /**
     * 删除商品出库单信息
     *
     * @param id 商品出库单主键
     * @return 结果
     */
    @Override
    public int deleteWarehousingOutById(String id) {
        return warehousingOutMapper.deleteById(id);
    }

    /**
     * 入库单推送到平台
     * 入库单以规格列表展示，即：以一个仓库下的一个运输/配送单下的一个供应商的一个商品的一个规格，区分货箱列表展示（规格下的存放的哪几个货箱）
     * 以供应商区分的map案列,实际以列表推送即可
     * {"210831090516920208":[{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"5","spuCode":"4","specId":"157169367745216","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"5","weight":6.27,"operator":"anonymousUser"},{"quantity":1,"boxNum":1,"boxCode":"7","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"5","spuCode":"4","specId":"1571699727452161","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"5","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"4","spuCode":"4","specId":"157169367727452161","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"4","weight":6.27,"operator":"anonymousUser"}]}],"210831090516992066":[{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"6","specId":"1571693679366742011","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516992066","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"}]}],"2831090516992020877":[{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"9","specId":"1571693679727452162","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2831090516992020877","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"},{"quantity":1,"boxNum":1,"boxCode":"8","weight":6.27,"operator":"anonymousUser"}]}],"2108310905169920":[{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"3","spuCode":"3","specId":"157169367936674201","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"3","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"3","specId":"1571693679366742017","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"}]}],"2108310905169920208":[{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"2","spuCode":"7","specId":"1571693679366742015","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"2","weight":6.27,"operator":"anonymousUser"}]}]}
     * <p>
     * 列表形式：
     * [{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"5","spuCode":"4","specId":"157169367745216","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"5","weight":6.27,"operator":"anonymousUser"},{"quantity":1,"boxNum":1,"boxCode":"7","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"5","spuCode":"4","specId":"1571699727452161","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"5","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"4","spuCode":"4","specId":"157169367727452161","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"4","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"6","specId":"1571693679366742011","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"210831090516992066","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"9","specId":"1571693679727452162","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2831090516992020877","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"},{"quantity":1,"boxNum":1,"boxCode":"8","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"3","spuCode":"3","specId":"157169367936674201","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"3","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"1","spuCode":"3","specId":"1571693679366742017","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"1","weight":6.27,"operator":"anonymousUser"}]},{"associatedOrderCode":"CGD1571693678477549568","type":"1","boxCode":"2","spuCode":"7","specId":"1571693679366742015","batchCode":"1571693679366742016","quantity":1,"weight":6.27,"supplierId":"2108310905169920208","producerId":"2108310905169920208","createBy":"anonymousUser","entryBoxDtoList":[{"quantity":1,"boxNum":1,"boxCode":"2","weight":6.27,"operator":"anonymousUser"}]}]
     *
     * @param warehousingout
     * @return void
     * @author yw
     * @date 2023-05-27 20:11:00
     */
    @Override
    public void commitToPlatform(WarehousingOut warehousingout) {
        if (StrUtil.isEmpty(warehousingout.getBatchCode())) {
            throw new UtilException("批次编号为空");
        }
        if (StrUtil.isEmpty(warehousingout.getAssociatedOrderCode())) {
            throw new UtilException("业务单号为空");
        }
        Warehouse warehouse = warehouseService.selectLocalWarehouseFront();
        if (warehouse != null) {
            warehousingout.setWarehouseCode(warehouse.getWarehouseCode());
            List<WarehousingOut> list = warehousingOutMapper.commitToPlatform(warehousingout);
            if (!list.isEmpty()) {
                //传为数据传输dto
                List<WarehousingOutDto> outDtoList = JSONUtil.toList(JSONUtil.toJsonStr(list), WarehousingOutDto.class);
                //根据供应商分组
                LinkedHashMap<String, List<WarehousingOutDto>> mapSupplier = outDtoList.stream().collect(Collectors.groupingBy(WarehousingOutDto::getSupplierCode, LinkedHashMap::new, Collectors.toList()));

                Map<String, List<WarehousingOutDto>> map = new HashMap<>();
                List<WarehousingOutDto> entryList = new ArrayList<>();
                /**供应商下的spu下的规格以货箱为单位展现，即：规格存放在多个货箱中**/
                mapSupplier.forEach((key, value) -> {
                    if (!value.isEmpty()) {
                        List<WarehousingOutDto> entryDtoList = new ArrayList<>();
                        //根据spu分组
                        LinkedHashMap<String, List<WarehousingOutDto>> mapSpu = value.stream().collect(Collectors.groupingBy(WarehousingOutDto::getSpuId, LinkedHashMap::new, Collectors.toList()));
                        mapSpu.forEach((mapSpuKey, mapSpuValue) -> {
                            //根据规格分组
                            LinkedHashMap<String, List<WarehousingOutDto>> mapSpec = mapSpuValue.stream().collect(Collectors.groupingBy(WarehousingOutDto::getSpecCode, LinkedHashMap::new, Collectors.toList()));
                            mapSpec.forEach((mapSpecKey, mapSpecValue) -> {
                                if (!mapSpecValue.isEmpty()) {
                                    //出库单以规格列表展示，即：以一个仓库下的一个运输/配送单下的一个供应商的一个商品的一个规格，区分货箱列表展示（规格下的存放的哪几个货箱）
                                    WarehousingOutDto dto = mapSpec.get(mapSpecKey).get(0);
                                    Spu spu = spuService.getById(dto.getSpuId());
                                    dto.setSpuCode(spu.getSpuCode());
                                    dto.setSpecId(dto.getSpecCode());
                                    List<WarehousingEntryBoxDto> dtoList = new ArrayList<>();
                                    mapSpecValue.forEach(specWarehouse -> {
                                        WarehousingEntryBoxDto warehousingEntryBoxDto = new WarehousingEntryBoxDto();
                                        warehousingEntryBoxDto.setQuantity(specWarehouse.getQuantity());
                                        warehousingEntryBoxDto.setBoxNum(1);
                                        warehousingEntryBoxDto.setBoxCode(specWarehouse.getBoxCode());
                                        warehousingEntryBoxDto.setWeight(specWarehouse.getWeight());
                                        warehousingEntryBoxDto.setOperator(specWarehouse.getCreateBy());
                                        warehousingEntryBoxDto.setCreateTime(LocalDateTimeUtil.format(specWarehouse.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
                                        dtoList.add(warehousingEntryBoxDto);
                                        dto.setBoxNum(dto.getBoxNum() + warehousingEntryBoxDto.getBoxNum());
                                    });
                                    //规格下的存放的货箱列表，即一个规格存放的N个货箱内
                                    dto.setEntryBoxDtoList(dtoList);
                                    //以规格为列表展示
                                    entryDtoList.add(dto);
                                }
                            });
                        });
                        map.put(key, entryDtoList);
                    }
                });
                log.info("map->" + JSONUtil.toJsonStr(map));
                map.forEach((k, v) -> {
                    entryList.addAll(v);
                });
                log.info("list->" + JSONUtil.toJsonStr(entryList));

                /**发送到数据转发中心**/
                String topic = warehouseService.selectRegionAreaTopic(warehouse);
                String tag = MqConstants.TAG_WAREHOUSE_OUT;
                try {
                    ParamInfo<WarehousingOutDto> info = new ParamInfo<>();
                    info.setList(entryList);
                    info.setWarehouseCode(warehouse.getWarehouseCode());
                    log.error("出库单：{}", JSON.toJSONString(info));
                    producerUtil.sendAsyncMsg(topic, tag, JSON.toJSONString(info).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
